/*******************************************************************************
 * Copyright (c) 2010 L.Carbonnaux.
 *******************************************************************************/

package org.lcx.taskvision.core.handler;

import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.mylyn.tasks.core.ITaskMapping;
import org.eclipse.mylyn.tasks.core.RepositoryResponse;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.mylyn.tasks.core.ITask.PriorityLevel;
import org.eclipse.mylyn.tasks.core.RepositoryResponse.ResponseKind;
import org.eclipse.mylyn.tasks.core.data.AbstractTaskDataHandler;
import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper;
import org.eclipse.mylyn.tasks.core.data.TaskAttributeMetaData;
import org.eclipse.mylyn.tasks.core.data.TaskData;
import org.lcx.taskvision.core.TaskVisionClient;
import org.lcx.taskvision.core.TaskVisionCorePlugin;
import org.lcx.taskvision.core.TaskVisionRepositoryConnector;
import org.lcx.taskvision.core.attribute.TaskVisionAttributeMapper;
import org.lcx.taskvision.core.attribute.TaskVisionAttribute;

import com.google.gdata.data.spreadsheet.ListEntry;


/**
 * @author Laurent Carbonnaux
 */
public class TaskVisionTaskDataHandler extends AbstractTaskDataHandler {

	private TaskVisionRepositoryConnector connector;

	private static final String SV_KEY = "svKey";

	
	public TaskVisionTaskDataHandler(TaskVisionRepositoryConnector connector) {
		this.connector = connector;
	}

	/**
	 * Method called when updating mylyn taskdata for any request to the repository (query, synchronization, ...)
	 */
	public TaskData createTaskDataFromListEntry(TaskRepository taskRepository, ListEntry listEntry,
			IProgressMonitor monitor) throws CoreException {
    	String id = listEntry.getCustomElements().getValue(TaskVisionAttribute.TASKID.getSvKey());
    	TaskData taskData = new TaskData(new TaskVisionAttributeMapper(taskRepository), 
    			TaskVisionCorePlugin.CONNECTOR_KIND,
    			taskRepository.getUrl(), id);
    	initializeTaskData(taskRepository, taskData, null, monitor);
    	updateTaskDataFromFeed(taskRepository, taskData, listEntry);
    	return taskData;
	}
	
	/**
	 * Update the task from query or task synchronization
	 */
	public void updateTaskDataFromFeed(TaskRepository taskRepository, TaskData data, 
			ListEntry listEntry) throws CoreException {
		
		try{
		Set<String> tags = listEntry.getCustomElements().getTags();
		for (String tag : tags) {
			
			TaskAttribute attr = data.getRoot().getAttribute(tag);

			String value = listEntry.getCustomElements().getValue(tag);
			
			if(attr==null) {
				attr = createAttibute(data, TaskVisionAttribute.DEFAULT, tag);
				TaskAttributeMetaData metaData = attr.getMetaData();
				if(value!=null && value.contains("\n"))
					metaData.setType(TaskAttribute.TYPE_LONG_RICH_TEXT);
				else
					metaData.setType(TaskAttribute.TYPE_SHORT_RICH_TEXT);
				metaData.setKind(TaskAttribute.KIND_DEFAULT);
				metaData.setLabel(tag+":");
				metaData.setReadOnly(false);
				metaData.putValue(SV_KEY, tag);
			}
			
			if(value!=null && value!="\n") {
				attr.setValue(value);
			} else {
				// set to blank for forcing display and respect of the entry feed
				attr.setValue("");
			}
			
		}
		} catch (Exception e){
			e.printStackTrace();
			throw new CoreException(new Status(Status.ERROR, TaskVisionCorePlugin.PLUGIN_ID, 1,
					"Error while synchronizing task\n\n" + e.getMessage(), e));
		}
	}
	
	/**
	 * Create task attribute for the given attribute type
	 * @param data, the task
	 * @param attribute, the attribute type
	 * @param tag, the name of the attribute
	 * @return
	 */
	public static TaskAttribute createAttibute(TaskData data, TaskVisionAttribute attribute, String tag) {
		TaskAttribute attr = data.getRoot().createAttribute(tag);
		TaskAttributeMetaData metaData = attr.getMetaData();
		metaData.setType(attribute.getType());
		metaData.setKind(attribute.getKind());
		metaData.setLabel(attribute.toString());
		metaData.setReadOnly(attribute.isReadOnly());
		metaData.putValue(SV_KEY, tag);
		return attr;
	}

	public static TaskAttribute createAttibute(TaskData data, TaskVisionAttribute attribute) {
		return createAttibute(data, attribute, attribute.getSvKey());
	}
	
	public void setDefaultAttribute(TaskData taskData) throws CoreException {
		TaskAttribute att;
		att = createAttibute(taskData, TaskVisionAttribute.TASKID);
		att = createAttibute(taskData, TaskVisionAttribute.SUMMARY);
		att.setValue("New Task");
		
		att = createAttibute(taskData, TaskVisionAttribute.PRIORITY);
		att.setValue(PriorityLevel.getDefault().getDescription());
		for (int i = 0; i < PriorityLevel.values().length; i++) {
			PriorityLevel p = PriorityLevel.values()[i];
			att.putOption(p.toString(), p.toString());
		}

		att = createAttibute(taskData, TaskVisionAttribute.COMPLETED);
		att.setValue("");

		att = createAttibute(taskData, TaskVisionAttribute.DESCRIPTION);
		att.setValue("");
		
	}
	
	@Override
	public TaskAttributeMapper getAttributeMapper(TaskRepository taskRepository) {
		return new TaskVisionAttributeMapper(taskRepository);
	}
	
	
	/**
	 * called when new task is created
	 */
	@Override
	public boolean initializeTaskData(TaskRepository repository, TaskData taskData, ITaskMapping initializationData,
			IProgressMonitor monitor) throws CoreException {
			setDefaultAttribute(taskData);
			return true;
	}

	@Override
	public RepositoryResponse postTaskData(TaskRepository repository, TaskData taskData,
		Set<TaskAttribute> oldAttributes, IProgressMonitor monitor) throws CoreException {
		TaskVisionClient client = connector.getClientManager().getClient(repository);
		String id = client.postTaskData(taskData);
		if (taskData.isNew()) {
			return new RepositoryResponse(ResponseKind.TASK_CREATED, id + "");
		} else {
			return new RepositoryResponse(ResponseKind.TASK_UPDATED, id + "");
		}
	}

}
